package org.nlp2rdf.navigator.benchmark;

import org.aksw.commons.util.random.RandomUtils;

import java.util.Random;

/**
 * Created by Claus Stadler
 * Date: Oct 15, 2010
 * Time: 4:55:58 PM
 */
public abstract class KFoldCrossValidationExperiment<E, D>
{
    protected int numPhases;


    protected Sample<E> all;
    protected KFoldCollection<E> kFolds;
    protected Random random;

    protected IGenericLearner<E, D> learner;
    protected IGenericClassifier<E, D> classifier;

    protected KFoldContext<E> currentFold;
    protected PhaseContext<E, D> currentPhase;

    protected int currentPhaseId = 0;
    protected int currentFoldId;


/*
public static <E, D> KFoldCrossValidationExperiment<E, D> create(Sample<E> all, KFoldCollection<E> kFolds, Random random, IGenericLearner<E, D> learner, IGenericClassifier<E, D> classifier)
{
    return new KFoldCrossValidationExperiment<E, D>(all, kFolds, random, learner, classifier);
}
*/

    public KFoldCrossValidationExperiment(Sample<E> all, KFoldCollection<E> kFolds, int numPhases, Random random, IGenericLearner<E, D> learner, IGenericClassifier<E, D> classifier)
    {
        this.all = all;
        this.kFolds = kFolds;
        this.numPhases = numPhases;
        this.random = random;
        this.learner = learner;
        this.classifier = classifier;
    }

    /**
     * FIXME Make this work like a JDBC-ResultSet: call next() to do the next step
     *
     */
    public void run()
    {
         currentFoldId = 0;
         for(KFoldContext<E> kFold : kFolds) {
             currentFold = kFold;

             Sample<E> init = new Sample<E>(
                     RandomUtils.randomSampleSet(currentFold.getTrainSample().getPositives(), 5, random),
                     RandomUtils.randomSampleSet(currentFold.getTrainSample().getNegatives(), 5, random));


             PhaseIterator<E, D> itPhase = new PhaseIterator<E, D>(all, currentFold.getTrainSample(), init, random, learner, classifier);

             currentPhaseId = 0;
             while(itPhase.hasNext() && currentPhaseId < numPhases) {
                  currentPhase = itPhase.next();

                  collectStats();

                  ++currentPhaseId;
             }

             ++currentFoldId;
         }
     }

    public abstract void collectStats();

    public Sample<E> getAll() {
        return all;
    }

    public KFoldCollection<E> getkFolds() {
        return kFolds;
    }

    public IGenericLearner<E, D> getLearner() {
        return learner;
    }

    public IGenericClassifier<E, D> getClassifier() {
        return classifier;
    }

    public Random getRandom() {
        return random;
    }

    public KFoldContext<E> getCurrentFold() {
        return currentFold;
    }

    public PhaseContext<E, D> getCurrentPhase() {
        return currentPhase;
    }

    public int getCurrentFoldId() {
        return currentFoldId;
    }

    public int getCurrentPhaseId() {
        return currentPhaseId;
    }

}